package main

import (
	"fmt"
	"time"
)

/*
goroutines:在 go 语言中，每一个并发的执行单元叫作一个 goroutine。
goroutine生成：当一个程序启动时，其主函数即在一个单独的 goroutine 中运行，我们叫它 main goroutine，main goroutine程序运行过程会生成
goroutine结束：每一个 goroutine 都是独立的。新的 gorountine 进行过程中， main goroutine 也会继续执行，当 main goroutine 执行结束后，所有的 goroutine 都结束 。

主函数返回时， 所有的 goroutine 都会被直接打断、程序退出。
除了从主函数退出或者直接终止程序之外， 没有其他的编程方法能够让一个 goroutine 来打断另一个执行，
但是可以通过 goroutine 之间的通信来让一个 goroutine 请求其他的 goroutine，并让被请求的 goroutine 自行结束执行。

goroutine就是轻量线程、协程，特性与线程几乎一样
*/
func main() {
	//启了一个 goroutine 去执行 spinner(), 但 main goroutine  还在执行
	//故 main goroutine 执行完最后一句 fmt.Printf() 后，子协程也需要结束，尽管还在 sleep()。
	go spinner(100 * time.Millisecond)
	const n = 45
	fmt.Println("开始计算45的阶梯数列")
	fibN := fib(n) // slow
	fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN)
}

func spinner(delay time.Duration) {
	for {
		for _, r := range `-\|/` {
			fmt.Printf("\r%c", r)
			time.Sleep(delay)
		}
	}
}

func fib(x int) int {
	if x < 2 {
		return x
	}
	return fib(x-1) + fib(x-2)
}
